/****************************************************
	文件：ControllerBase.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2021/1/14 13:25:56
	功能：控制层 基类
*****************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using HTFW.Consts;
using HTFW.Core;

namespace HTFW.UI
{
    public abstract class ControllerBase<TV, TM>
        where TV : ViewBase
        where TM : ModelBase

    {
        protected TM mModel;
        protected TV mView;

        public TM Model => mModel;
        public TV View => mView;

        public ControllerBase(TV view, TM model)
        {
            mView = view;
            mModel = model;
        }

        /// <summary>
        /// 初始化控制器
        /// </summary>
        public virtual void Init()
        {
            InitModel();
            InitView();
            RegisterEvents();
        }

        /// <summary>
        /// 销毁控制器
        /// </summary>
        public virtual void Dispose()
        {
            DisposeModel();
            DisposeView();
            DisposeEventTimerFrameCorou();
        }

        /// <summary>
        /// 初始化数据模型
        /// </summary>
        protected abstract void InitModel();

        /// <summary>
        /// 销毁数据模型
        /// </summary>
        protected virtual void DisposeModel()
        {
            mModel.Dispose();
        }

        /// <summary>
        /// 初始化视图层
        /// </summary>
        protected abstract void InitView();

        /// <summary>
        /// 销毁视图层
        /// </summary>
        protected virtual void DisposeView()
        {
        }

        /// <summary>
        /// 注册事件（内部自动完成事件注销）
        /// </summary>
        protected abstract void RegisterEvents();


        //------------------------------ 帮助方法 ------------------------------//

        #region 内部帮助方法

        /// <summary>
        /// 内部事件集合
        /// </summary>
        Dictionary<EventType, List<HCallBack>> mEventDict = new Dictionary<EventType, List<HCallBack>>();

        /// <summary>
        /// 内部计时任务 Id 列表
        /// </summary>
        List<int> mTimeTaskIdLst = new List<int>();

        /// <summary>
        /// 内部帧任务 Id 列表
        /// </summary>
        List<int> mFrameTaskIdLst = new List<int>();

        /// <summary>
        /// 协程列表
        /// </summary>
        List<IRoutineHandle> mRoutineLst = new List<IRoutineHandle>();


        /// <summary>
        /// 注册事件（隐藏/关闭界面时自动注销）
        /// </summary>
        /// <param name="eventType"></param>
        /// <param name="callBack"></param>
        protected void AddEvent(EventType eventType, HCallBack callBack)
        {
            EventCenter.Subscribe(eventType, callBack);

            if (mEventDict.ContainsKey(eventType))
            {
                mEventDict[eventType].Add(callBack);
            }
            else
            {
                List<HCallBack> cbLst = new List<HCallBack>();
                cbLst.Add(callBack);
                mEventDict.Add(eventType, cbLst);
            }
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="eventType"></param>
        /// <param name="p"></param>
        protected void Fire(EventType eventType, params object[] p)
        {
            EventCenter.Publish(eventType, p);
        }

        /// <summary>
        /// 计时任务（隐藏/关闭界面时自动销毁）
        /// </summary>
        /// <param name="callBack"></param>
        /// <param name="delayTime"></param>
        /// <param name="timeUnit"></param>
        /// <param name="loopCount"></param>
        protected void AddTimer(Action<int> callBack, double delayTime, TimeUnit timeUnit = TimeUnit.MilliSecond,
            int loopCount = 1)
        {
            mTimeTaskIdLst.Add(
                HTDriver.GlobalContext.TimerContext.AddTimeTask(callBack, delayTime, timeUnit, loopCount));
        }

        /// <summary>
        /// 帧任务（隐藏/关闭界面时自动销毁）
        /// </summary>
        /// <param name="callBack"></param>
        /// <param name="delayFrame"></param>
        /// <param name="loopCount"></param>
        protected void AddFrame(Action<int> callBack, int delayFrame, int loopCount = 1)
        {
            mFrameTaskIdLst.Add(HTDriver.GlobalContext.TimerContext.AddFrameTask(callBack, delayFrame, loopCount));
        }

        /// <summary>
        /// 开启协程（隐藏/关闭界面时自动销毁）
        /// </summary>
        /// <param name="routine"></param>
        protected void AddCoroutine(IEnumerator routine)
        {
            mRoutineLst.Add(CoroutineService.Instance.Start(routine, true));
        }

        /// <summary>
        /// 注销内部事件/计时任务/帧任务/协程
        /// </summary>
        void DisposeEventTimerFrameCorou()
        {
            foreach (var item in mTimeTaskIdLst)
                HTDriver.GlobalContext.TimerContext.RemoveTimeTask(item);

            foreach (var item in mFrameTaskIdLst)
                HTDriver.GlobalContext.TimerContext.RemoveFrameTask(item);

            foreach (var item in mEventDict)
            {
                foreach (var cb in item.Value)
                    EventCenter.Unsubscribe(item.Key, cb);
            }

            foreach (var item in mRoutineLst)
                item.Stop();

            mTimeTaskIdLst.Clear();
            mFrameTaskIdLst.Clear();
            mEventDict.Clear();
            mRoutineLst.Clear();
        }

        #endregion
    }
}